package com.yjzx.util.common.util.BeanUtils;

import com.yjzx.util.common.execption.UtilException;
import org.hibernate.validator.HibernateValidator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yjzx
 * @date 2024/1/3
 * @description 参数校验
 */
public class ValidationUtil {
    private static final Validator VALIDATOR;
    private static final Set<Class<?>> CLASS_SET;

    static {
        VALIDATOR = Validation.byProvider(HibernateValidator.class)
                .configure()
                .failFast(true)
                .buildValidatorFactory()
                .getValidator();
        CLASS_SET = new HashSet<>(Arrays.asList(Byte.class, Byte.TYPE, Short.class, Short.TYPE, Integer.class, Integer.TYPE,
                Long.class, Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE, BigDecimal.class, String.class, Object.class));
    }

    /**
     * javax.validation注解校验
     *
     * @param t      将要校验的对象
     * @param groups 分组
     * @param <T>
     * @Description: 校验方法
     */
    public static <T> void validate(T t, Class<?>... groups) {
        Set<ConstraintViolation<T>> set = t != null && groups != null && groups.length > 0 ? VALIDATOR.validate(t, groups) : VALIDATOR.validate(t);
        if (set != null && set.size() > 0) {
            throw new UtilException(set.stream().map(x -> new StringBuilder(String.valueOf(x.getPropertyPath())).append(":").append(x.getMessage())).collect(Collectors.joining(";")));
        }
        if (t != null && !CLASS_SET.contains(t.getClass())) {
            Field[] fields = t.getClass().getDeclaredFields();
            try {
                for (Field field : fields) {
                    if (Object.class != field.getType() && CLASS_SET.contains(field.getType())) {
                        continue;
                    }
                    field.setAccessible(true);
                    Object o = field.get(t);
                    if (o != null && !CLASS_SET.contains(o.getClass())) {
                        if (o instanceof Collection && ((((Collection<?>) o).size()) > 0)) {
                            for (Object o1 : (Collection<?>) o) {
                                if (o1 != null) {
                                    if (CLASS_SET.contains(o1.getClass())) {
                                        break;
                                    } else {
                                        validate(o1, groups);
                                    }
                                }
                            }
                        } else {
                            validate(o, groups);
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
